%{
import java.io.*;
import tree.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Vector;
import java.util.Iterator;
%}


%token  NL
%token <dval> NUMBER
%token  PIU
%token  MENO
%token  PER
%token  DIVISO


%type	<dval>	exp

%left MENO PIU 
%right PER DIVISO 

%%


 input : 
				{
		
		Vector<String> attributi = new Vector<>();} 
	|	input line 		{
		
		Vector<String> attributi = new Vector<>();
		attributi.add(new String(""));} 
;
 line : 
		NL 		{
		
		Vector<String> attributi = new Vector<>();
		attributi.add(new String(""));} 
	|	exp NL 		{
		
		Vector<String> attributi = new Vector<>();
		attributi.add(new String(""));
		attributi.add(new String(Double.toString($1)));} 
;
 exp : 
		NUMBER 		{$$ = $1;
				System.out.println(Double.toString($$));
		Vector<String> attributi = new Vector<>();
		attributi.add(new String(Double.toString($$)));
		attributi.add(new String(""));
		attributi.add(new String(Double.toString($1)));} 
	|	exp PIU exp 		{$$ = $1+$3;
				System.out.println(Double.toString($$));
		Vector<String> attributi = new Vector<>();
		attributi.add(new String(Double.toString($$)));
		attributi.add(new String(Double.toString($1)));
		attributi.add(new String("+"));
		attributi.add(new String(Double.toString($3)));;
		this.addNode(attributi);} 
	|	exp MENO exp 		{$$ = $1-$3;
				System.out.println(Double.toString($$));
		Vector<String> attributi = new Vector<>();
		attributi.add(new String(Double.toString($$)));
		attributi.add(new String(Double.toString($1)));
		attributi.add(new String("-"));
		attributi.add(new String(Double.toString($3)));;
		this.addNode(attributi);} 
	|	exp PER exp 		{$$ = $1*$3;
				System.out.println(Double.toString($$));
		Vector<String> attributi = new Vector<>();
		attributi.add(new String(Double.toString($$)));
		attributi.add(new String(Double.toString($1)));
		attributi.add(new String("*"));
		attributi.add(new String(Double.toString($3)));;
		this.addNode(attributi);} 
	|	exp DIVISO exp 		{$$ = $1/$3;
				System.out.println(Double.toString($$));
		Vector<String> attributi = new Vector<>();
		attributi.add(new String(Double.toString($$)));
		attributi.add(new String(Double.toString($1)));
		attributi.add(new String("/"));
		attributi.add(new String(Double.toString($3)));;
		this.addNode(attributi);} 
;

%%
private ScannerLex lexer;
private boolean first = true;

HashMap idMap = new HashMap();

//NTree<Nodo> tree = new NTree<Nodo>();

NTree<Nodo> tree = new NTree<Nodo>();

TreeUtil<Nodo> util = new TreeUtil<Nodo>();

BTree<Nodo> btree = new BTree<Nodo>();
TreeUtil<Nodo> butil = new TreeUtil<Nodo>();

public Parser(Reader r, boolean debugMe) {
	lexer = new ScannerLex(r,this);
	yydebug=debugMe;
        tree = new NTree<Nodo>();
}

public Parser(Reader r, boolean debugMe, NTree tree) {
	lexer = new ScannerLex(r,this);
	yydebug=debugMe;
        this.tree = tree;
}

public ScannerLex getScanner() {
	return lexer;
}

private int yylex () {
    int yyl_return = -1;
    try {
      yylval = new ParserVal(0);
      yyl_return = lexer.yylex();
    //System.out.println("yyl_return"+yyl_return);
    }
    catch (IOException e) {
      System.err.println("IO error :"+e);
    }
    return yyl_return;
  }
  
  public void yyerror (String error) {
    System.err.println ("Error: " + error);
  }
  
  
  
  private void addNode(String valore) {
       String [] stringval= new String[1];
       stringval[0] = valore;
  	Nodo nd = new Nodo(stringval);
  	if(first) {
  		Node<Nodo> root = tree.addRoot(nd);
  		first = false;
  	}
  	else {
  		
  		Node<Nodo> child = tree.addChildren(tree.root(),nd);
  	}
  	
  	System.out.println("NODO");
  }
  


private void addNode(Vector<String> vector) {
      
        if(vector.size()>0) {
            
            Nodo child = null;
            Nodo rootN = null;
            
            if(tree.isEmpty()) {
                
                rootN = new Nodo(vector.firstElement());
                Node<Nodo> root = tree.addRoot(rootN);
                

                

                for(int i=1; i<vector.size(); i++){

                        child = new Nodo((String)vector.get(i));
                        System.out.println("NOME CHILD: "+child.getNome());
                        System.out.println("NOME ROOT: "+rootN.getNome());
                        //if(!child.getNome().equals(rootN.getNome()))
                            tree.addChildren(root,child);
                    }
                
            }
            else {

                //System.out.println("ELSE ADD NODE");
                rootN = new Nodo(vector.firstElement());
                if(tree.root().getElement().toString().equals(rootN.toString()))
                    return;
                Node<Nodo> root = tree.changeRoot(rootN);
            



                for(int i=1; i<vector.size(); i++){
                        Boolean bool = true;
                        child = new Nodo((String)vector.get(i));
                        System.out.println("NOME CHILD: "+child.getNome());
                        System.out.println("NOME ROOT: "+rootN.getNome());
                        Iterator it = tree.children(root).iterator();
                        while (it.hasNext()) {
                            Node<Nodo> nd;
                            nd = (Node<Nodo>) it.next();
                                if(nd.getElement().getNome().equals(child.getNome()))
                                bool=false;
                        }
                        
                        if(bool)
                            tree.addChildren(root,child);
                        
                    }
            
            }
            //util.stampa(tree);
        }
        
  }
  
  private void addNode(String valore,String sx,String op,String dx) {
  	System.out.println("VAL: "+valore+" SX: "+sx+" OP: "+op+" DX: "+dx+" FIRST: "+first);
  	
	if(first) {
		//Nodo rootN = new Nodo(op,valore);
                
//		Nodo bn1N = new Nodo(stringdx);
	//	Nodo bn2N = new Nodo(stringsx);
		//BNode<Nodo> broot = btree.addRoot(rootN);
		//BNode<Nodo> bn1 = btree.insertLeft(broot, bn1N);
		//BNode<Nodo> bn2 = btree.insertRight(broot, bn2N);
	
		//butil.stampa(btree);
	
                String [] stringval= new String[1];
                String [] stringop= new String[1];
                String [] stringdx= new String[1];
                String [] stringsx= new String[1];
                stringdx[0] = dx;
                stringsx[0] = sx;
                stringval[0] = valore;
                stringop[0] = op;
		Nodo rootN = new Nodo(stringval);
		Nodo leftN = new Nodo(stringsx);
		Nodo rightN = new Nodo(stringdx);
		Nodo opN = new Nodo(stringop);
		Node<Nodo> root = tree.addRoot(rootN);
		Node<Nodo> left = tree.addChildren(root,leftN);
		Node<Nodo> operatore = tree.addChildren(root,opN);
		Node<Nodo> right = tree.addChildren(root,rightN);
		first = false;
		//util.stampa(tree);
		
	}
	//In questo caso cambio la root in quanto la costruzione e' bottomUp
	else {
		
		//Nodo rootN = new Nodo(op,valore);
//		Nodo bn1N = new Nodo(dx);
	//	Nodo bn2N = new Nodo(sx);
		//BNode<Nodo> broot = btree.changeRoot(rootN);
		//BNode<Nodo> bn1 = btree.insertLeft(broot, bn1N);
		//BNode<Nodo> bn2 = btree.insertRight(broot, bn2N);
		
		//butil.stampa(btree);
	


                String [] stringval= new String[1];
                String [] stringop= new String[1];
                String [] stringdx= new String[1];
                String [] stringsx= new String[1];
                stringdx[0] = dx;
                stringsx[0] = sx;
                stringval[0] = valore;
                stringop[0] = op;
	
		Nodo rootN = new Nodo(stringval);
		//Nodo leftN = new Nodo(stringsx);
		Nodo rightN = new Nodo(stringdx);
		Nodo opN = new Nodo(stringop);
	
		Node<Nodo> root = tree.changeRoot(rootN);
		//System.out.println("1");
		//util.stampa(tree);
		Node<Nodo> operatore = tree.addChildren(root,opN);
		//System.out.println("2");
		//util.stampa(tree);
		Node<Nodo> right = tree.addChildren(root,rightN);
		//System.out.println("3");
		//util.stampaNodi(tree);
	}
    }

        
private void addNode(String valore,String sx,String dx) {
  	  	
	if(first) {
		//Nodo rootN = new Nodo(op,valore);
                
//		Nodo bn1N = new Nodo(stringdx);
	//	Nodo bn2N = new Nodo(stringsx);
		//BNode<Nodo> broot = btree.addRoot(rootN);
		//BNode<Nodo> bn1 = btree.insertLeft(broot, bn1N);
		//BNode<Nodo> bn2 = btree.insertRight(broot, bn2N);
	
		//butil.stampa(btree);
	
                String [] stringval= new String[1];
        
                String [] stringdx= new String[1];
                String [] stringsx= new String[1];
                stringdx[0] = dx;
                stringsx[0] = sx;
                stringval[0] = valore;
        
		Nodo rootN = new Nodo(stringval);
		Nodo leftN = new Nodo(stringsx);
		Nodo rightN = new Nodo(stringdx);
	
		Node<Nodo> root = tree.addRoot(rootN);
		Node<Nodo> left = tree.addChildren(root,leftN);
	
		Node<Nodo> right = tree.addChildren(root,rightN);
		first = false;
		//util.stampa(tree);
		
	}
	//In questo caso cambio la root in quanto la costruzione e' bottomUp
	else {
		
		//Nodo rootN = new Nodo(op,valore);
//		Nodo bn1N = new Nodo(dx);
	//	Nodo bn2N = new Nodo(sx);
		//BNode<Nodo> broot = btree.changeRoot(rootN);
		//BNode<Nodo> bn1 = btree.insertLeft(broot, bn1N);
		//BNode<Nodo> bn2 = btree.insertRight(broot, bn2N);
		
		//butil.stampa(btree);
	


                String [] stringval= new String[1];
        
                String [] stringdx= new String[1];
                String [] stringsx= new String[1];
                stringdx[0] = dx;
                stringsx[0] = sx;
                stringval[0] = valore;
        
	
		Nodo rootN = new Nodo(stringval);
		//Nodo leftN = new Nodo(stringsx);
		Nodo rightN = new Nodo(stringdx);
		
		Node<Nodo> root = tree.changeRoot(rootN);
		//System.out.println("1");
		//util.stampa(tree);
	
		//System.out.println("2");
		//util.stampa(tree);
		Node<Nodo> right = tree.addChildren(root,rightN);
		//System.out.println("3");
		//util.stampaNodi(tree);
	}
        util.stampa(tree);
    }



        private void addIdToMap(String id,double val) {
            idMap.put(id,val);
        }

        private double getIdFromMap(String id) {
            if(idMap.containsKey(id))
                return (double)idMap.get(id);
            else
                return 0;
        }
